package com.bifang.common.helper;

import cn.hutool.crypto.SecureUtil;
import com.bifang.common.constant.CacheConst;
import com.bifang.common.constant.enums.common.EquipmentTypeEnum;
import com.bifang.common.vo.SessionInfo;
import com.bifang.common.vo.TokenVO;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/** 登录工具类 */
@Service
public class TokenLoginHelper {
    @Autowired
    RedisHelper redisHelper;

    @Value("${system.config.token.timeout}")
    private Long timeout;

    @Value("${system.config.token.app.timeout}")
    private Long appTimeout;

    @Value("${system.config.token.refresh.timeout}")
    private Long refreshTimeout;

    @Value("${system.same.login.cnt}")
    private Integer sameLoginCnt;

    /** 登录 */
    public TokenVO login(SessionInfo sessionInfo) {
        String accessToken = makeToken(sessionInfo);
        TokenVO tokenVO = new TokenVO();
        tokenVO.setAccessToken(accessToken);
        if (StringUtils.isNotBlank(sessionInfo.getUserId())) {
            tokenVO.setUniId(SecureUtil.md5(sessionInfo.getUserId()));
        }
        String redisKey = CacheConst.ACCESS_TOKEN + ":" + accessToken;
        sessionInfo.setExpireFreshTime(System.currentTimeMillis());
        tokenVO.setExpireFreshTime(System.currentTimeMillis());
        String userKey =
                SecureUtil.md5(
                        sessionInfo.getUserId()
                                + ":"
                                + sessionInfo.getLoginType()
                                + ":"
                                + sessionInfo.getEquipmentType()
                                + ":"
                                + sessionInfo.getUserType());
        String userTokenKey = CacheConst.USER_LOGIN_TOKEN;
        if (sameLoginCnt == null) {
            sameLoginCnt = 1;
        }
        List<String> tokenList = new ArrayList<>();
        if (redisHelper.hHasKey(userTokenKey, userKey)) {
            Object obj = redisHelper.hget(userTokenKey, userKey);
            if (obj instanceof String) {
                redisHelper.hdel(userTokenKey, userKey);
                String oldToken = (String) obj;
                redisHelper.del(CacheConst.ACCESS_TOKEN + ":" + oldToken);
            } else {
                tokenList = (List<String>) redisHelper.hget(userTokenKey, userKey);
                if (!CollectionUtils.isEmpty(tokenList) && tokenList.size() >= sameLoginCnt) {
                    String oldToken = tokenList.get(0);
                    tokenList.remove(0);
                    redisHelper.del(CacheConst.ACCESS_TOKEN + ":" + oldToken);
                }
            }
        }
        tokenList.add(accessToken);
        sessionInfo.setUserTokenKey(userKey);
        if (EquipmentTypeEnum.PC.getType().equals(sessionInfo.getEquipmentType())) {
            sessionInfo.setExpireMinute(timeout);
            tokenVO.setExpireMinute(timeout);
            redisHelper.set(redisKey, sessionInfo, timeout);
            redisHelper.hset(userTokenKey, userKey, tokenList);
        } else {
            sessionInfo.setExpireMinute(appTimeout);
            tokenVO.setExpireMinute(appTimeout);
            redisHelper.set(redisKey, sessionInfo, appTimeout);
            redisHelper.hset(userTokenKey, userKey, tokenList);
        }
        return tokenVO;
    }

    public String makeToken(SessionInfo sessionInfo) {
        Long sysTime = System.currentTimeMillis();
        return SecureUtil.md5(
                sessionInfo.getUserId()
                        + ":"
                        + sessionInfo.getUserType()
                        + ":"
                        + sessionInfo.getEquipmentType()
                        + ":"
                        + sessionInfo.getLoginType()
                        + ":"
                        + sysTime);
    }

    /** 退出 */
    public void logout(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return;
        }
        String redisKey = CacheConst.ACCESS_TOKEN + ":" + accessToken;
        if (redisHelper.hasKey(redisKey)) {
            SessionInfo sessionInfo = (SessionInfo) redisHelper.get(redisKey);
            if (sessionInfo != null) {
                String userKey = sessionInfo.getUserTokenKey();
                String userTokenKey = CacheConst.USER_LOGIN_TOKEN;
                if (redisHelper.hHasKey(userTokenKey, userKey)) {

                    Object obj = redisHelper.hget(userTokenKey, userKey);
                    if (obj instanceof String) {
                        redisHelper.hdel(userTokenKey, userKey);
                    } else {
                        List<String> tokenList = (List<String>) obj;
                        if (tokenList.contains(accessToken)) {
                            tokenList.remove(accessToken);
                        }
                        if (CollectionUtils.isEmpty(tokenList)) {
                            redisHelper.hdel(userTokenKey, userKey);
                        } else {
                            redisHelper.hset(userTokenKey, userKey, tokenList);
                        }
                    }
                }
            }
            redisHelper.del(redisKey);
        }
    }
    /** 校验token是否存在或过期 */
    public boolean checkToken(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return false;
        }
        SessionInfo sessionInfo = getSessionInfo(accessToken);
        if (sessionInfo == null) {
            return false;
        }
        if (System.currentTimeMillis() - sessionInfo.getExpireFreshTime()
                > sessionInfo.getExpireMinute()) {
            return false;
        }
        return true;
    }
    /** 获取用户信息,重新更新缓存过期时间 */
    public SessionInfo getSessionInfo(String accessToken) {
        if (StringUtils.isBlank(accessToken)) {
            return null;
        }
        String redisKey = CacheConst.ACCESS_TOKEN + ":" + accessToken;
        if (redisHelper.hasKey(redisKey)) {
            SessionInfo sessionInfo = (SessionInfo) redisHelper.get(redisKey);
            sessionInfo.setExpireFreshTime(System.currentTimeMillis());
            if (EquipmentTypeEnum.PC.getType().equals(sessionInfo.getEquipmentType())) {
                sessionInfo.setExpireMinute(timeout);
                redisHelper.set(redisKey, sessionInfo, timeout);
            } else {
                sessionInfo.setExpireMinute(appTimeout);
                redisHelper.set(redisKey, sessionInfo, appTimeout);
            }
            return sessionInfo;
        }
        return null;
    }
    /** 更新token */
    public SessionInfo updateSessionInfo(String accessToken, SessionInfo sessionInfo) {
        if (StringUtils.isBlank(accessToken)) {
            return null;
        }
        String redisKey = CacheConst.ACCESS_TOKEN + ":" + accessToken;
        if (redisHelper.hasKey(redisKey)) {
            sessionInfo.setExpireFreshTime(System.currentTimeMillis());
            if (EquipmentTypeEnum.PC.getType().equals(sessionInfo.getEquipmentType())) {
                sessionInfo.setExpireMinute(timeout);
                redisHelper.set(redisKey, sessionInfo, timeout);
            } else {
                sessionInfo.setExpireMinute(appTimeout);
                redisHelper.set(redisKey, sessionInfo, appTimeout);
            }
            return sessionInfo;
        }
        return null;
    }
}
